﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using UserSurface;
using ApplicationCore;

namespace EnzymeLaborTool
{
    public partial class EnzymeStandardsCtrl : UserControl
    {
        private Guid _newItemUId = new Guid("11111111-1111-1111-1111-111111111111");
        private MainSurface _surface;
        private EnzymeDBDataContext _dataContext;

        public EnzymeStandardsCtrl()
        {
            InitializeComponent();
        }

        public void Init(MainSurface ms)
        {
            _surface = ms;
            _dataContext = ms.CurrentDataContext; //use a common data context
            BindMaterial();
            BindAnalyte();
            BindProtocol();
            kryptonCheckSetAnalyteTypes.CheckedButtonChanged += new EventHandler(kryptonCheckSetAnalyteTypes_CheckedButtonChanged);
        }


        #region Binding


        private void kryptonCheckSetAnalyteTypes_CheckedButtonChanged(object sender, EventArgs e)
        {
            BindAnalyte();
        }

        private void materialBindingSource_CurrentChanged(object sender, EventArgs e)
        {
            BindActivity(null);
        }

        private void filterMaterialTextBox_TextChanged(object sender, EventArgs e)
        {
            BindMaterial();
        }

        private void filterEnzymesTextBox_TextChanged(object sender, EventArgs e)
        {
            BindAnalyte();
        }

        private void filterActivityTextBox_TextChanged(object sender, EventArgs e)
        {
            BindActivity(null);
        }

        private void BindMaterial()
        {
            var q = from x in _dataContext.MaterialViews
                    select x;



            if (!string.IsNullOrEmpty(filterMaterialTextBox.Text))
                q = from x in q
                    where x.Name.ToLower().Contains(filterMaterialTextBox.Text.ToLower().Trim())
                    select x;

            materialBindingSource.DataSource = from x in q orderby x.Name select x;
        }

        private void BindActivity(ActivityView selectActivity)
        {
            MaterialView mv = materialBindingSource.Current as MaterialView;
            if (mv != null)
            {
                var q = from x in _dataContext.ActivityViews
                        where x.MaterialUId == mv.UId
                        select x;
                if (!string.IsNullOrEmpty(filterActivityTextBox.Text))
                    q = from x in q
                        where x.Analyte.ToLower().Contains(filterActivityTextBox.Text.ToLower().Trim())
                        select x;

                activityBindingSource.DataSource = from x in q orderby x.Analyte select x;

                if (selectActivity != null)
                {
                    var av = _dataContext.ActivityViews.SingleOrDefault(x =>
                              x.ProtocolUId == selectActivity.ProtocolUId
                           && x.MaterialUId == selectActivity.MaterialUId
                           && x.EnzymeUid == selectActivity.EnzymeUid);
                    if (av != null)
                    {
                        activityBindingSource.Position = activityBindingSource.IndexOf(av);
                    }
                }

            }
            else
                activityBindingSource.DataSource = null;
        }

        private void BindProtocol()
        {
            //using (EnzymeDBDataContext dataContext = _surface.GetDataContext())
            //{
                EnzymeView ev = enzymeBindingSource.Current as EnzymeView;
                if (ev != null)
                {

                    var q = from x in _dataContext.ProtocolViews
                            where x.UId != Guid.Empty
                            where x.Enzyme_Fk == ev.UId
                            orderby x.Name
                            select x;

                    var p = from x in _dataContext.ProtocolViews
                            where x.UId == Guid.Empty

                            select x;

                    var s = p.Union(q);
                    protocolBindingSource.DataSource = s;
                }
            //}
        }

        private void BindAnalyte()
        {
            var q = from x in _dataContext.EnzymeViews
                    select x;

            if (kryptonCheckButtonEnzymes.Checked)
                q = from x in q where x.Type == "Enzyme" select x;
            if (kryptonCheckButtonMetabolites.Checked)
                q = from x in q where x.Type == "Metabolite" select x;

            if (!string.IsNullOrEmpty(filterEnzymesTextBox.Text))
                q = from x in q
                    where x.Analyte.ToLower().Contains(filterEnzymesTextBox.Text.ToLower().Trim())
                    select x;

            enzymeBindingSource.DataSource = from x in q orderby x.Analyte select x;
        }

        private void enzymeBindingSource_CurrentChanged(object sender, EventArgs e)
        {
            BindProtocol();
        }
        #endregion

        #region Security
        private void ApplyMaterialSecurity()
        {
            materialDataGridView.AllowUserToDeleteRows = false;
            materialDataGridView.ReadOnly = true;
            materialBindingSource.AllowNew = false;



            materialDeleteItem.Enabled = false;

            if (_surface.SecDescriptor.Rights.ContainsKey("Material"))
            {
                foreach (TableRight tr in _surface.SecDescriptor.Rights["Material"])
                {
                    switch (tr)
                    {
                        case TableRight.Insert:
                            {

                                materialBindingSource.AllowNew = true;
                                break;
                            }
                        case TableRight.Delete:
                            {
                                materialDataGridView.AllowUserToDeleteRows = true;
                                materialDeleteItem.Enabled = true;
                                break;
                            }
                        case TableRight.Update:
                            {
                                materialDataGridView.ReadOnly = false;
                                break;
                            }
                    }
                }
            }

        }

        private void ApplyEnzymeSecurity()
        {
            enzymeDataGridView.AllowUserToDeleteRows = false;
            enzymeDataGridView.ReadOnly = true;
            enzymeBindingSource.AllowNew = false;
            enzymeDeleteItem.Enabled = false;

            if (_surface.SecDescriptor.Rights.ContainsKey("EnzymeCodes"))
            {
                foreach (TableRight tr in _surface.SecDescriptor.Rights["EnzymeCodes"])
                {
                    switch (tr)
                    {
                        case TableRight.Insert:
                            {

                                enzymeBindingSource.AllowNew = true;
                                break;
                            }
                        case TableRight.Delete:
                            {
                                enzymeDataGridView.AllowUserToDeleteRows = true;
                                enzymeDeleteItem.Enabled = true;
                                break;
                            }
                        case TableRight.Update:
                            {
                                enzymeDataGridView.ReadOnly = false;
                                break;
                            }
                    }
                }
            }

        }

        private void ApplyActivitySecurity()
        {
            activityDataGridView.AllowUserToDeleteRows = false;
            activityDataGridView.ReadOnly = true;
            //enzymeBindingSource.AllowNew = false;
            activityAddNewItem.Enabled = false;
            activityDeleteItem.Enabled = false;

            if (_surface.SecDescriptor.Rights.ContainsKey("Activity"))
            {
                foreach (TableRight tr in _surface.SecDescriptor.Rights["Activity"])
                {
                    switch (tr)
                    {
                        case TableRight.Insert:
                            {

                                activityAddNewItem.Enabled = true;
                                break;
                            }
                        case TableRight.Delete:
                            {
                                activityDataGridView.AllowUserToDeleteRows = true;
                                activityDeleteItem.Enabled = true;
                                break;
                            }
                        case TableRight.Update:
                            {
                                activityDataGridView.ReadOnly = false;
                                break;
                            }
                    }
                }
            }
        }
        #endregion
        
        #region CRUD Material

        //toolbar initiated add-action
        private void materialAddNewItem_Click(object sender, EventArgs e)
        {
            if (!materialDataGridView.IsCurrentCellInEditMode)
            {
                materialBindingSource.AddNew();
                materialDataGridView.BeginEdit(true);
            }
        }



        //create a default Material for adding
        private void materialBindingSource_AddingNew(object sender, AddingNewEventArgs e)
        {
            e.NewObject = new MaterialView { UId = _newItemUId, Name = "NewMaterial" };
        }

        //validate added or updated material data
        private void materialDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            if (materialDataGridView.IsCurrentCellInEditMode)
            {
                var mv = materialDataGridView.Rows[e.RowIndex].DataBoundItem as MaterialView;
                if (mv == null)
                {
                    return;
                }
                if (string.IsNullOrEmpty(e.FormattedValue.ToString()))
                {
                    materialDataGridView.Rows[e.RowIndex].ErrorText = "The Material name can't be empty.";
                    e.Cancel = true;
                }
                else
                {
                    var check = _dataContext.MaterialViews.SingleOrDefault(x => x.UId != mv.UId && x.Name.ToLower() == e.FormattedValue.ToString().ToLower().Trim());
                    if (check != null)
                    {
                        materialDataGridView.Rows[e.RowIndex].ErrorText = "Material with this name already exist.";
                        e.Cancel = true;
                    }
                }
            }
        }

        //save added and updated material
        private void materialDataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {

            materialDataGridView.Rows[e.RowIndex].ErrorText = null;
            MaterialView mv = null;
            try
            {
                mv = materialDataGridView.Rows[e.RowIndex].DataBoundItem as MaterialView;
            }
            catch (IndexOutOfRangeException)
            {
                //handles case where new row is edited and then escape key is pressed to cancel the new row
            }

            if (mv != null)
            {
                if (mv.UId == _newItemUId)
                {
                    mv.UId = _surface.AddMaterial(mv.Name);
                }
                else
                {
                    _surface.UpdateMaterial(mv.UId, mv.Name);
                }
            }
        }

        //toolbar initiated delete-action
        private void materialDeleteItem_Click(object sender, EventArgs e)
        {
            if (ConfirmMaterialDelete())
            {
                MaterialView mv = materialBindingSource.Current as MaterialView;
                if (mv != null)
                {
                    _surface.DeleteMaterial(mv.UId);
                    materialBindingSource.RemoveCurrent();
                }
            }
        }

        //gridview initiated delete-action
        private void dataGridViewMaterial_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            e.Cancel = !ConfirmMaterialDelete();
        }

        //delete material 
        private void materialDataGridView_UserDeletedRow(object sender, DataGridViewRowEventArgs e)
        {
            var mv = e.Row.DataBoundItem as MaterialView;
            if (mv != null)
            {
                _surface.DeleteMaterial(mv.UId);
            }
        }

        //request user confirmation for delete
        private bool ConfirmMaterialDelete()
        {
            return MessageBox.Show("Are you sure you want to delete the current material and all related enzyme activities?", "Confirm material delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
                == DialogResult.Yes;
        }

        #endregion

        #region CRUD Enzyme

        //toolbar initiated add-action
        private void enzymeAddNewItem_Click(object sender, EventArgs e)
        {
            if (!enzymeDataGridView.IsCurrentCellInEditMode)
            {
                enzymeBindingSource.AddNew();
                enzymeDataGridView.BeginEdit(true);
            }
        }

        //create a default Enzyme for adding
        private void enzymeBindingSource_AddingNew(object sender, AddingNewEventArgs e)
        {
            if (kryptonCheckButtonEnzymes.Checked)
                e.NewObject = new EnzymeView { UId = _newItemUId, Analyte = "NewEnzyme", Code = "", SlopeRatio = 1, Type = "Enzyme" };
            else
                e.NewObject = new EnzymeView { UId = _newItemUId, Analyte = "NewMetabolite", Code = "", SlopeRatio = 1, Type = "Metabolite" };
        }

        //validate added and updated enzyme data
        private void enzymeDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            if (enzymeDataGridView.IsCurrentCellInEditMode)
            {
                DataGridViewRow row = enzymeDataGridView.Rows[e.RowIndex];
                //DataGridViewColumn col = enzymeDataGridView.Columns[e.ColumnIndex];
                row.Tag = null;
                var ev = row.DataBoundItem as EnzymeView;
                if (ev == null)
                {
                    return;
                }
                foreach (DataGridViewCell cell in row.Cells)
                {
                    DataGridViewColumn col = enzymeDataGridView.Columns[cell.ColumnIndex];
                    if (col.DataPropertyName == "Enzyme")
                    {
                        string val = row.Cells[col.Name].EditedFormattedValue.ToString();
                        if (string.IsNullOrEmpty(val))
                        {
                            enzymeDataGridView.Rows[e.RowIndex].ErrorText = "An enzyme name is required.";
                            if (cell.ColumnIndex == e.ColumnIndex)
                                e.Cancel = true;
                            else
                                row.Tag = "hasErrors";
                        }
                        else
                        {
                            var check = _dataContext.EnzymeViews.SingleOrDefault(x => x.UId != ev.UId && x.Analyte.ToLower() == val.ToLower().Trim());
                            if (check != null)
                            {
                                enzymeDataGridView.Rows[e.RowIndex].ErrorText = "Enzyme with this name already exist.";
                                if (cell.ColumnIndex == e.ColumnIndex)
                                    e.Cancel = true;
                                else
                                    row.Tag = "hasErrors";
                            }
                        }
                    }
                    if (col.DataPropertyName == "Code")
                    {
                        string val = row.Cells[col.Name].EditedFormattedValue.ToString();
                        if (string.IsNullOrEmpty(val))
                        {
                            enzymeDataGridView.Rows[e.RowIndex].ErrorText = "An enzyme code is required.";
                            if (cell.ColumnIndex == e.ColumnIndex)
                                e.Cancel = true;
                            else
                                row.Tag = "hasErrors";
                        }
                        else
                        {
                            var check = _dataContext.EnzymeViews.SingleOrDefault(x => x.UId != ev.UId && x.Code.ToLower() == val.ToLower().Trim());
                            if (check != null)
                            {
                                enzymeDataGridView.Rows[e.RowIndex].ErrorText = "Enzyme with this code already exist.";
                                if (cell.ColumnIndex == e.ColumnIndex)
                                    e.Cancel = true;
                                else
                                    row.Tag = "hasErrors";
                            }
                        }
                    }

                    if (col.DataPropertyName == "SlopeRatio")
                    {
                        string val = row.Cells[col.Name].EditedFormattedValue.ToString();
                        double sr;
                        if (!double.TryParse(val, out sr))
                        {
                            enzymeDataGridView.Rows[e.RowIndex].ErrorText = "SlopeRatio is not a valid number.";
                            if (cell.ColumnIndex == e.ColumnIndex)
                                e.Cancel = true;
                            else
                                row.Tag = "hasErrors";
                        }
                    }
                }








            }
        }

        //save added and updated enzyme
        private void enzymeDataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            DataGridViewRow row = enzymeDataGridView.Rows[e.RowIndex];
            if (row.Tag != null && row.Tag.ToString() == "hasErrors") //check for outstanding errors to solve
                return;

            enzymeDataGridView.Rows[e.RowIndex].ErrorText = null;
            EnzymeView mv = null;
            try
            {
                mv = enzymeDataGridView.Rows[e.RowIndex].DataBoundItem as EnzymeView;
            }
            catch (IndexOutOfRangeException)
            {
                //handles case where new row is edited and then escape key is pressed to cancel the new row
            }



            if (mv != null)
            {
                if (mv.UId == _newItemUId)
                {
                    mv.UId = _surface.AddAnalyte(mv.Analyte, mv.Code, mv.Type, mv.SlopeRatio);
                }
                else
                {
                    _surface.UpdateAnalyte(mv.UId, mv.Analyte, mv.Code, mv.SlopeRatio);
                }
            }
        }

        //toolbar initiated delete-action
        private void enzymeDeleteItem_Click(object sender, EventArgs e)
        {
            if (ConfirmEnzymeDelete())
            {
                EnzymeView mv = enzymeBindingSource.Current as EnzymeView;
                if (mv != null)
                {
                    _surface.DeleteAnalyte(mv.UId);
                    enzymeBindingSource.RemoveCurrent();
                }
            }
        }

        //gridview initiated delete-action
        private void enzymeDataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            e.Cancel = !ConfirmEnzymeDelete();
        }

        //delete enzyme 
        private void enzymeDataGridView_UserDeletedRow(object sender, DataGridViewRowEventArgs e)
        {
            var mv = e.Row.DataBoundItem as EnzymeView;
            if (mv != null)
            {
                _surface.DeleteAnalyte(mv.UId);
            }
        }

        //request user conformation for delete
        private bool ConfirmEnzymeDelete()
        {
            return MessageBox.Show("Are you sure you want to delete the current enzyme?\r\nThis action will also delete all corresponding raw data!", "Confirm enzyme delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
                == DialogResult.Yes;
        }

        #endregion

        #region CRUD Activity
        //button initiated add-action
        private void activityAddNewItem_Click(object sender, EventArgs e)
        {
            var prot = protocolBindingSource.Current as ProtocolView;
            var mat = materialBindingSource.Current as MaterialView;
            var enz = enzymeBindingSource.Current as EnzymeView;
            if (prot != null && mat != null && enz != null)
            {
                ActivityView av = _dataContext.ActivityViews.SingleOrDefault(x =>
                        x.ProtocolUId == prot.UId
                     && x.MaterialUId == mat.UId
                     && x.EnzymeUid == enz.UId);
                if (av == null)
                {
                    _surface.AddActivity(prot.UId, mat.UId, enz.UId);
                    av = _dataContext.ActivityViews.Single(x =>
                          x.ProtocolUId == prot.UId
                       && x.MaterialUId == mat.UId
                       && x.EnzymeUid == enz.UId);
                    BindActivity(av);
                    activityDataGridView.CurrentCell = activityDataGridView.CurrentRow.Cells[3];
                    activityDataGridView.BeginEdit(true);
                }
            }
        }

        //support autocomplete for units
        private void activityDataGridView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            DataGridViewColumn dgv = activityDataGridView.Columns[activityDataGridView.CurrentCell.ColumnIndex];
            if (dgv.DataPropertyName == "Unit")
            {
                TextBox tb = e.Control as TextBox;
                tb.AutoCompleteMode = AutoCompleteMode.Suggest;
                tb.AutoCompleteSource = AutoCompleteSource.CustomSource;
                using (EnzymeDBDataContext context = _surface.GetDataContext())
                {
                    var units = (from x in context.Units orderby x.Name select x.Name).ToArray();
                    tb.AutoCompleteCustomSource.Clear();
                    tb.AutoCompleteCustomSource.AddRange(units);
                }
            }
        }

        //create a default activity for adding
        private void activityDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            if (activityDataGridView.IsCurrentCellInEditMode)
            {
                var mv = activityDataGridView.Rows[e.RowIndex].DataBoundItem as ActivityView;
                if (mv == null)
                {
                    return;
                }


                string val = e.FormattedValue.ToString().Trim().ToLower();
                DataGridViewColumn col = activityDataGridView.Columns[e.ColumnIndex];
                if (col.DataPropertyName == "Value")
                {
                    double sr;
                    if (!double.TryParse(val, out sr))
                    {
                        activityDataGridView.Rows[e.RowIndex].ErrorText = "Activity is not a valid number.";
                        e.Cancel = true;

                    }
                }
                else if (col.DataPropertyName == "Unit")
                {
                    using (EnzymeDBDataContext context = _surface.GetDataContext())
                    {
                        if (context.Units.SingleOrDefault(x => x.Name == val) == null)
                        {
                            activityDataGridView.Rows[e.RowIndex].ErrorText = "Unknown unit.";
                            e.Cancel = true;
                        }
                    }
                }
            }
        }

        //validate added or updated activity
        private void activityDataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {


            ActivityView av = null;
            activityDataGridView.Rows[e.RowIndex].ErrorText = null;

            try
            {
                av = activityDataGridView.Rows[e.RowIndex].DataBoundItem as ActivityView;
            }
            catch (IndexOutOfRangeException)
            {
                //handles case where new row is edited and then escape key is pressed to cancel the new row
            }

            if (av != null)
            {

                _surface.UpdateActivity(av.ProtocolUId, av.MaterialUId, av.EnzymeUid, av.Value, av.Unit);
            }
        }

        //toolbar initiated delete-action
        private void activityDeleteItem_Click(object sender, EventArgs e)
        {
            if (ConfirmActivityDelete())
            {
                ActivityView mv = activityBindingSource.Current as ActivityView;
                if (mv != null)
                {
                    _surface.DeleteActivity(mv.ProtocolUId, mv.MaterialUId, mv.EnzymeUid);
                    activityBindingSource.RemoveCurrent();
                }
            }
        }

        //gridview initiated delete-action
        private void activityDataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            e.Cancel = !ConfirmActivityDelete();
        }

        //delete activity 
        private void activityDataGridView_UserDeletedRow(object sender, DataGridViewRowEventArgs e)
        {
            var mv = e.Row.DataBoundItem as ActivityView;
            if (mv != null)
            {
                _surface.DeleteActivity(mv.ProtocolUId, mv.MaterialUId, mv.EnzymeUid);
            }
        }

        //request user conformation for delete
        private bool ConfirmActivityDelete()
        {
            return MessageBox.Show("Are you sure you want to delete the current enzyme activity?", "Confirm enzyme activity delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
                == DialogResult.Yes;
        }
        #endregion

        #region DIALOGS
        private void kryptonButton1_Click(object sender, EventArgs e)
        {
            EnzymeView enzyme = enzymeBindingSource.Current as EnzymeView;
            ProtocolFrm protfrm = new ProtocolFrm();
            protfrm.Init(_surface,enzyme );
            protfrm.ShowDialog(this);
            BindProtocol();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            UnitFrm unitFrm = new UnitFrm();
            unitFrm.Init(_surface);
            unitFrm.ShowDialog(this);
          //  _dataContext.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues,_dataContext.ProtocolViews);
            BindProtocol();
        } 
        #endregion

      

       





























    }
}
